package com.maixun.lib_base.mvp

import com.alibaba.sdk.android.oss.model.PutObjectRequest
import com.maixun.lib_base.upfile.UpFileConstants
import com.maixun.lib_base.upfile.UpFileNetWork
import com.maixun.lib_network.entity.NetBaseEntity
import com.maixun.lib_base.entity.UpFileResultBeen
import com.maixun.lib_choosefile.entity.FileItem
import com.maixun.lib_network.OSSManager
import com.maixun.lib_network.entity.STSResultBeen
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Function
import io.reactivex.schedulers.Schedulers
import java.util.*

/**
 * 作者：Lmoumou
 * 时间：2020/7/14 09:54
 */
abstract class BaseModelImpl : BaseContract.BaseModel {

    private val fileAreaMap by lazy { hashMapOf<Int, STSResultBeen>() }
    private val upLoadFileService by lazy { UpFileNetWork.getService() }

    override fun <T> mNetWork(
        observer: Observer<NetBaseEntity<T>>,
        observable: Observable<NetBaseEntity<T>>
    ) {
        observable.compose { upstream ->
            upstream.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
        }.subscribe(observer)
    }

    override fun mUpLoadFile(
        fileList: MutableList<FileItem>,
        areaTag: Int
    ): Observable<MutableList<UpFileResultBeen>>? {
        val upFileList = fileList.filter { it.isLocal() || it.getFilePath().isNotEmpty() }
        val stsResultBeen = fileAreaMap[areaTag]

        return if (stsResultBeen == null || stsResultBeen.isInvalid()) {
            when (areaTag) {
                UpFileConstants.HEAD -> upLoadFileService.headSTS()
                else -> null
            }?.flatMap(object :
                Function<NetBaseEntity<STSResultBeen>, Observable<MutableList<UpFileResultBeen>>> {
                override fun apply(t: NetBaseEntity<STSResultBeen>): Observable<MutableList<UpFileResultBeen>> {
                    t.result?.let {
                        return asyncUpLoadCopy(upFileList, it, areaTag)
                    }
                    return Observable.error(NullPointerException("获取STS配置数据异常！"))
                }
            })
        } else {
            asyncUpLoadCopy(upFileList, stsResultBeen, areaTag)
        }
    }

    private fun asyncUpLoadCopy(
        fileList: List<FileItem>,
        stsResultBeen: STSResultBeen,
        areaTag: Int
    ): Observable<MutableList<UpFileResultBeen>> {
        val ossClient = OSSManager.getInstance().getOSSClient(stsResultBeen, areaTag)
        return Observable.fromIterable(fileList)
            .flatMap { t ->
                Observable.just(t)
                    .map { t2 ->
                        val id = UUID.randomUUID().toString()
                        val suffix =
                            t2.getFilePath().substring(t2.getFilePath().lastIndexOf(".") + 1)
                        val key = "${stsResultBeen.prefix}/$id.$suffix"
                        val put = PutObjectRequest(stsResultBeen.bucket, key, t2.getFilePath())
                        val result = ossClient.putObject(put)
                        UpFileResultBeen(key, result.statusCode, areaTag)
                    }
            }
            .toList()
            .flatMapObservable { t ->
                Observable.create<MutableList<UpFileResultBeen>> {
                    it.onNext(t)
                    it.onComplete()
                }
            }
    }


}